import os
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
from pathlib import Path


class ArchiveScanner:
    def __init__(self):
        """
        压缩包统计工具
        """
        self.root = tk.Tk()
        self.root.title("压缩包统计工具")
        self.root.geometry("800x600")
        self.root.resizable(True, True)

        # 支持的压缩包格式
        self.archive_extensions = ('.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz')

        # 统计数据
        self.total_archives = 0
        self.archives_by_type = {}
        self.archive_list = []

        self.setup_ui()

    def setup_ui(self):
        """
        创建用户界面
        """
        # 标题
        title_frame = tk.Frame(self.root, pady=20)
        title_frame.pack()
        tk.Label(
            title_frame,
            text="压缩包统计工具",
            font=("Microsoft YaHei UI", 18, "bold")
        ).pack()

        # 说明
        instruction_frame = tk.Frame(self.root)
        instruction_frame.pack(pady=10)
        instruction_text = """功能说明：
扫描指定文件夹及其子文件夹，统计所有压缩包文件
支持格式：ZIP、RAR、7Z、TAR、GZ、BZ2、XZ"""

        tk.Label(
            instruction_frame,
            text=instruction_text,
            font=("Microsoft YaHei UI", 10),
            justify="left"
        ).pack()

        # 按钮框架
        button_frame = tk.Frame(self.root)
        button_frame.pack(pady=20)

        # 选择文件夹按钮
        tk.Button(
            button_frame,
            text="选择要扫描的文件夹",
            command=self.select_folder_and_scan,
            font=("Microsoft YaHei UI", 12),
            bg="#4CAF50",
            fg="white",
            width=20,
            height=2
        ).pack(side="left", padx=10)

        # 导出结果按钮
        self.export_btn = tk.Button(
            button_frame,
            text="导出统计结果",
            command=self.export_results,
            font=("Microsoft YaHei UI", 12),
            bg="#2196F3",
            fg="white",
            width=20,
            height=2,
            state="disabled"
        )
        self.export_btn.pack(side="left", padx=10)

        # 结果显示区域
        result_frame = tk.Frame(self.root)
        result_frame.pack(fill="both", expand=True, padx=20, pady=10)

        # 统计信息框架
        stats_frame = tk.Frame(result_frame)
        stats_frame.pack(fill="x", pady=(0, 10))

        self.stats_label = tk.Label(
            stats_frame,
            text="请选择文件夹开始扫描...",
            font=("Microsoft YaHei UI", 12, "bold"),
            bg="#f0f0f0",
            relief="sunken",
            pady=10
        )
        self.stats_label.pack(fill="x")

        # 详细列表
        tk.Label(result_frame, text="压缩包详细列表：", font=("Microsoft YaHei UI", 12, "bold")).pack(anchor="w")

        # 创建文本框和滚动条
        self.text_area = scrolledtext.ScrolledText(
            result_frame,
            wrap=tk.WORD,
            font=("Consolas", 10),
            bg="white",
            fg="black"
        )
        self.text_area.pack(fill="both", expand=True)

    def select_folder_and_scan(self):
        """
        选择文件夹并开始扫描
        """
        folder = filedialog.askdirectory(title="选择要扫描的文件夹")
        if folder:
            self.scan_folder(folder)

    def scan_folder(self, folder_path):
        """
        扫描文件夹中的所有压缩包
        """
        # 重置统计数据
        self.total_archives = 0
        self.archives_by_type = {}
        self.archive_list = []

        # 清空文本区域
        self.text_area.delete(1.0, tk.END)
        self.text_area.insert(tk.END, f"正在扫描文件夹: {folder_path}\n")
        self.text_area.insert(tk.END, "=" * 80 + "\n\n")
        self.root.update()

        try:
            # 递归扫描文件夹
            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    file_ext = os.path.splitext(file)[1].lower()

                    # 检查是否是压缩包
                    if file_ext in self.archive_extensions:
                        self.total_archives += 1

                        # 按类型统计
                        if file_ext not in self.archives_by_type:
                            self.archives_by_type[file_ext] = 0
                        self.archives_by_type[file_ext] += 1

                        # 添加到列表
                        file_size = self.get_file_size(file_path)
                        relative_path = os.path.relpath(file_path, folder_path)

                        archive_info = {
                            'name': file,
                            'path': file_path,
                            'relative_path': relative_path,
                            'extension': file_ext,
                            'size': file_size,
                            'folder': os.path.dirname(relative_path)
                        }
                        self.archive_list.append(archive_info)

            # 显示结果
            self.display_results(folder_path)

        except Exception as e:
            messagebox.showerror("错误", f"扫描过程中发生错误: {str(e)}")

    def get_file_size(self, file_path):
        """
        获取文件大小（格式化显示）
        """
        try:
            size_bytes = os.path.getsize(file_path)
            if size_bytes < 1024:
                return f"{size_bytes} B"
            elif size_bytes < 1024 * 1024:
                return f"{size_bytes / 1024:.1f} KB"
            elif size_bytes < 1024 * 1024 * 1024:
                return f"{size_bytes / (1024 * 1024):.1f} MB"
            else:
                return f"{size_bytes / (1024 * 1024 * 1024):.1f} GB"
        except:
            return "未知"

    def display_results(self, folder_path):
        """
        显示扫描结果
        """
        # 更新统计信息
        if self.total_archives == 0:
            stats_text = "未发现任何压缩包文件"
        else:
            type_stats = ", ".join([f"{ext}: {count}个" for ext, count in sorted(self.archives_by_type.items())])
            stats_text = f"共发现 {self.total_archives} 个压缩包 ({type_stats})"

        self.stats_label.config(text=stats_text)

        # 清空并重新填充文本区域
        self.text_area.delete(1.0, tk.END)

        if self.total_archives == 0:
            self.text_area.insert(tk.END, "未发现任何压缩包文件。\n\n")
            self.text_area.insert(tk.END, "支持的格式：ZIP、RAR、7Z、TAR、GZ、BZ2、XZ")
            self.export_btn.config(state="disabled")
            return

        # 显示按类型统计
        self.text_area.insert(tk.END, "=== 按类型统计 ===\n")
        for ext, count in sorted(self.archives_by_type.items()):
            self.text_area.insert(tk.END, f"{ext.upper():<8} {count:>6} 个\n")

        self.text_area.insert(tk.END, f"{'总计':<8} {self.total_archives:>6} 个\n\n")

        # 显示详细列表
        self.text_area.insert(tk.END, "=== 详细列表 ===\n")
        self.text_area.insert(tk.END, f"{'序号':<4} {'文件名':<30} {'类型':<6} {'大小':<10} {'所在文件夹'}\n")
        self.text_area.insert(tk.END, "-" * 100 + "\n")

        # 按文件夹分组显示
        archives_by_folder = {}
        for archive in self.archive_list:
            folder = archive['folder'] if archive['folder'] else "根目录"
            if folder not in archives_by_folder:
                archives_by_folder[folder] = []
            archives_by_folder[folder].append(archive)

        index = 1
        for folder, archives in sorted(archives_by_folder.items()):
            if len(archives_by_folder) > 1:  # 只有多个文件夹时才显示文件夹标题
                self.text_area.insert(tk.END, f"\n📁 {folder}\n")

            for archive in sorted(archives, key=lambda x: x['name']):
                self.text_area.insert(tk.END,
                    f"{index:<4} {archive['name']:<30} {archive['extension']:<6} "
                    f"{archive['size']:<10} {archive['relative_path']}\n")
                index += 1

        # 启用导出按钮
        self.export_btn.config(state="normal")

        # 滚动到顶部
        self.text_area.see(1.0)

    def export_results(self):
        """
        导出统计结果到文件
        """
        if self.total_archives == 0:
            messagebox.showwarning("提示", "没有可导出的数据")
            return

        # 选择保存位置
        file_path = filedialog.asksaveasfilename(
            title="保存统计结果",
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )

        if file_path:
            try:
                with open(file_path, 'w', encoding='utf-8') as f:
                    # 写入标题
                    f.write("压缩包统计报告\n")
                    f.write("=" * 50 + "\n")
                    f.write(f"生成时间: {Path().absolute()}\n")
                    f.write(f"总计: {self.total_archives} 个压缩包\n\n")

                    # 写入按类型统计
                    f.write("=== 按类型统计 ===\n")
                    for ext, count in sorted(self.archives_by_type.items()):
                        f.write(f"{ext.upper():<8} {count:>6} 个\n")
                    f.write(f"{'总计':<8} {self.total_archives:>6} 个\n\n")

                    # 写入详细列表
                    f.write("=== 详细列表 ===\n")
                    f.write(f"{'序号':<4} {'文件名':<40} {'类型':<6} {'大小':<12} {'完整路径'}\n")
                    f.write("-" * 120 + "\n")

                    for index, archive in enumerate(self.archive_list, 1):
                        f.write(f"{index:<4} {archive['name']:<40} {archive['extension']:<6} "
                               f"{archive['size']:<12} {archive['path']}\n")

                messagebox.showinfo("成功", f"统计结果已保存到:\n{file_path}")

            except Exception as e:
                messagebox.showerror("错误", f"保存文件失败: {str(e)}")

    def run(self):
        """
        运行应用程序
        """
        self.root.mainloop()


if __name__ == "__main__":
    app = ArchiveScanner()
    app.run()